#pragma once
#include <stdarg.h>
#include <iostream>
#include <time.h>
#include <pthread.h>
#include <fstream>

bool g_issave = false; // 是否保存到文件中
const char *logname = "log.txt";

enum level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "Debug";
    case INFO:
        return "Info";
    case WARNING:
        return "Warning";
    case ERROR:
        return "error";
    case FATAL:
        return "fatal";
    default:
        break;
    }
    return "unkown";
}

std::string GetTimeString() // 获取时间
{
    time_t cur_time = time(nullptr);
    struct tm *format_time = localtime(&cur_time);
    char buffer[1024];
    snprintf(buffer, sizeof(buffer), "%d-%d-%d %d:%d:%d",
             format_time->tm_year + 1900,
             format_time->tm_mon + 1,
             format_time->tm_mday,
             format_time->tm_hour,
             format_time->tm_min,
             format_time->tm_sec);
    return buffer;
}

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 日志等级 时间 代码所在的文件名/行数 日志的内容
void LogMessage(std::string filename, int line, bool issave, int level, const char *format, ...)
{
    va_list arg;
    char buffer[1024];
    va_start(arg, format);
    vsnprintf(buffer, sizeof(buffer), format, arg);
    va_end(arg);
    pthread_mutex_lock(&mutex);
    std::string message = "[" + LevelToString(level) + "]" +
                          "[line:" + std::to_string(line) + "]" +
                          "[filename:" + filename + "]" +
                          "[" + GetTimeString() + "]" +
                          buffer;
    if (g_issave)
    {
        // 往文件中写入
        std::ofstream out(logname, std::ofstream::app);
        out << message << '\n';
        out.close();
    }
    else
    {
        std::cout << message << std::endl;
    }
    pthread_mutex_unlock(&mutex);
}

#define Log(level, format, ...)                                                 \
    do                                                                          \
    {                                                                           \
        LogMessage(__FILE__, __LINE__, g_issave, level, format, ##__VA_ARGS__); \
    } while (false)

#define EnableFIle()     \
    do                   \
    {                    \
        g_issave = true; \
    } while (false)
#define EnableScreen()    \
    do                    \
    {                     \
        g_issave = false; \
    } while (false)